#!/bin/bash

# Squid 代理服务器安装脚本 (支持SSL)
# 适用于 CentOS/RHEL/Fedora (使用 dnf)

set -e  # 遇到错误立即退出

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_step() {
    echo -e "${BLUE}[STEP]${NC} $1"
}

# 检查是否为 root 用户
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本需要 root 权限运行"
        log_info "请使用: sudo $0"
        exit 1
    fi
}

# 获取服务器IP地址
get_server_ip() {
    # 尝试获取公网IP
    SERVER_IP=$(curl -s ifconfig.me 2>/dev/null || curl -s ipinfo.io/ip 2>/dev/null || curl -s icanhazip.com 2>/dev/null)
    
    if [[ -z "$SERVER_IP" ]]; then
        # 如果无法获取公网IP，使用本地IP
        SERVER_IP=$(ip route get 8.8.8.8 | awk '{print $7; exit}')
    fi
    
    if [[ -z "$SERVER_IP" ]]; then
        log_warn "无法自动获取IP地址，请手动输入"
        read -p "请输入服务器IP地址: " SERVER_IP
    fi
    
    log_info "检测到服务器IP: $SERVER_IP"
}

# 安装 Squid
install_squid() {
    log_step "开始安装 Squid 代理服务器..."
    
    # 更新系统
    log_info "更新系统包..."
    dnf update -y
    
    # 安装必要的包
    log_info "安装 Squid 和相关工具..."
    dnf install -y squid httpd-tools openssl firewalld
    
    log_info "Squid 安装完成"
}

# 备份原配置文件
backup_config() {
    log_step "备份原始配置文件..."
    
    if [[ -f /etc/squid/squid.conf ]]; then
        cp /etc/squid/squid.conf /etc/squid/squid.conf.backup.$(date +%Y%m%d_%H%M%S)
        log_info "原配置文件已备份"
    fi
}

# 创建用户认证
setup_auth() {
    log_step "设置用户认证..."
    
    # 获取用户名和密码
    read -p "请输入代理用户名 [默认: proxyuser]: " PROXY_USER
    PROXY_USER=${PROXY_USER:-proxyuser}
    
    while true; do
        read -s -p "请输入代理密码: " PROXY_PASS
        echo
        read -s -p "请确认代理密码: " PROXY_PASS_CONFIRM
        echo
        
        if [[ "$PROXY_PASS" == "$PROXY_PASS_CONFIRM" ]]; then
            break
        else
            log_error "密码不匹配，请重新输入"
        fi
    done
    
    # 创建密码文件
    htpasswd -cb /etc/squid/passwd "$PROXY_USER" "$PROXY_PASS"
    chown squid:squid /etc/squid/passwd
    chmod 640 /etc/squid/passwd
    
    log_info "用户认证设置完成"
}

# 生成SSL证书
setup_ssl() {
    log_step "生成SSL证书..."
    
    # 创建SSL目录
    mkdir -p /etc/squid/ssl
    cd /etc/squid/ssl
    
    # 获取域名或使用IP
    read -p "请输入域名 [默认使用IP: $SERVER_IP]: " DOMAIN
    DOMAIN=${DOMAIN:-$SERVER_IP}
    
    log_info "为域名/IP生成证书: $DOMAIN"
    
    # 1. 生成私钥
    log_info "生成私钥..."
    openssl genrsa -out $DOMAIN.key 2048
    
    # 2. 生成证书签名请求 (CSR)
    log_info "生成证书签名请求..."
    openssl req -new -key $DOMAIN.key -out $DOMAIN.csr -subj "/C=CN/ST=State/L=City/O=Organization/OU=IT/CN=$DOMAIN"
    
    # 3. 生成自签名证书
    log_info "生成自签名证书..."
    openssl req -x509 -new -nodes -key $DOMAIN.key -days 3650 -out $DOMAIN.crt -subj "/C=CN/ST=State/L=City/O=Organization/OU=IT/CN=$DOMAIN"
    
    # 4. 重新签名证书（可选步骤，这里简化处理）
    log_info "最终处理证书..."
    openssl x509 -req -in $DOMAIN.csr -CA $DOMAIN.crt -CAkey $DOMAIN.key -CAcreateserial -out $DOMAIN.crt -days 3650
    
    # 合并证书和私钥为PEM格式
    cat $DOMAIN.crt $DOMAIN.key > $DOMAIN.pem
    
    # 设置权限
    chown -R squid:squid /etc/squid/ssl
    chmod -R 600 /etc/squid/ssl/*
    
    # 保存域名供后续使用
    echo "$DOMAIN" > /etc/squid/ssl/domain.txt
    
    log_info "SSL证书生成完成"
    log_info "证书文件: /etc/squid/ssl/$DOMAIN.crt"
    log_info "私钥文件: /etc/squid/ssl/$DOMAIN.key"
    log_info "PEM文件: /etc/squid/ssl/$DOMAIN.pem"
}

# 创建支持SSL的 Squid 配置文件
create_config() {
    log_step "创建 Squid 配置文件..."
    
    # 读取域名
    DOMAIN=$(cat /etc/squid/ssl/domain.txt 2>/dev/null || echo "$SERVER_IP")
    
    cat > /etc/squid/squid.conf << EOF
#
# Squid 代理服务器配置文件 (支持SSL)
# 自动生成于: $(date)
# 服务器IP: $SERVER_IP
# 域名: $DOMAIN
#

# ============================================
# 基本认证配置
# ============================================
auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic children 5
auth_param basic realm Squid Proxy Server
auth_param basic credentialsttl 2 hours

# ============================================
# ACL (访问控制列表) 定义
# ============================================

# 定义安全端口
acl SSL_ports port 443
acl SSL_ports port 8443
acl Safe_ports port 80          # http
acl Safe_ports port 443         # https


# 定义CONNECT方法
acl CONNECT method CONNECT

# 定义认证用户
acl authenticated proxy_auth REQUIRED

# ============================================
# HTTP 访问控制规则
# ============================================

# 拒绝访问不安全端口
http_access deny !Safe_ports

# 拒绝 CONNECT 到非 SSL 端口
http_access deny CONNECT !SSL_ports

# 允许已认证用户访问（所有人都可以连接，只要有账号密码）
http_access allow authenticated

# 拒绝所有其他访问
http_access deny all

# ============================================
# 网络配置
# ============================================

# HTTP 端口 (监听所有接口)
http_port 0.0.0.0:4001

# HTTPS 端口 (SSL代理)
https_port 0.0.0.0:4002 cert=/etc/squid/ssl/$DOMAIN.pem

# ============================================
# 基本配置
# ============================================

# 缓存目录配置
cache_dir ufs /var/spool/squid 1000 16 256

# 缓存内存设置
cache_mem 256 MB

# 日志配置
access_log /var/log/squid/access.log
cache_log /var/log/squid/cache.log

# DNS 配置
dns_nameservers 8.8.8.8 8.8.4.4

# 连接超时设置
connect_timeout 60 seconds
read_timeout 300 seconds

# 主机名
visible_hostname proxy-server

# 隐藏版本信息
httpd_suppress_version_string on

# 新版本SSL安全设置（替代过时的指令）
tls_outgoing_options options=NO_SSLv2,NO_SSLv3,NO_TLSv1
tls_outgoing_options cipher=HIGH:!aNULL:!MD5

EOF
    
    log_info "Squid 配置文件创建完成"
}


# 启动服务
start_service() {
    log_step "启动 Squid 服务..."
    
    # 停止可能存在的Squid服务
    if systemctl is-active --quiet squid; then
        log_info "停止现有的Squid服务..."
        systemctl stop squid
        sleep 2
    fi
    
    # 清理可能存在的PID文件
    if [[ -f /var/run/squid.pid ]]; then
        rm -f /var/run/squid.pid
    fi
    
    # 初始化缓存目录
    squid -z
    
    # 启用并启动 Squid
    systemctl enable squid
    systemctl start squid
    
    # 检查服务状态
    sleep 3
    if systemctl is-active --quiet squid; then
        log_info "Squid 服务启动成功"
    else
        log_error "Squid 服务启动失败"
        log_info "查看详细错误信息: journalctl -u squid -f"
        exit 1
    fi
}

# 显示配置信息
show_info() {
    DOMAIN=$(cat /etc/squid/ssl/domain.txt 2>/dev/null || echo "$SERVER_IP")
    
    echo
    echo -e "${GREEN}===========================================${NC}"
    echo -e "${GREEN}     Squid 代理服务器配置完成！${NC}"
    echo -e "${GREEN}===========================================${NC}"
    echo
    echo -e "${BLUE}代理服务器信息:${NC}"
    echo -e "  服务器地址: ${YELLOW}$SERVER_IP${NC}"
    echo -e "  域名: ${YELLOW}$DOMAIN${NC}"
    echo -e "  HTTP代理端口: ${YELLOW}4001${NC}"
    echo -e "  HTTPS代理端口: ${YELLOW}4002${NC}"
    echo -e "  用户名: ${YELLOW}$PROXY_USER${NC}"
    echo -e "  密码: ${YELLOW}[已设置]${NC}"
    echo
    echo -e "${BLUE}客户端配置:${NC}"
    echo -e "  HTTP代理: ${YELLOW}$SERVER_IP:4001${NC}"
    echo -e "  HTTPS代理: ${YELLOW}$SERVER_IP:4002${NC}"
    echo -e "  SSL证书: ${YELLOW}/etc/squid/ssl/$DOMAIN.crt${NC}"
    echo
    echo -e "${BLUE}管理命令:${NC}"
    echo -e "  查看状态: ${YELLOW}systemctl status squid${NC}"
    echo -e "  重启服务: ${YELLOW}systemctl restart squid${NC}"
    echo -e "  查看日志: ${YELLOW}tail -f /var/log/squid/access.log${NC}"
    echo
    echo -e "${YELLOW}注意: 使用HTTPS代理时，客户端需要信任自签名证书${NC}"
    echo -e "${YELLOW}证书位置: /etc/squid/ssl/$DOMAIN.crt${NC}"
    echo
}

# 主函数
main() {
    echo -e "${GREEN}===========================================${NC}"
    echo -e "${GREEN}     Squid 代理服务器安装脚本 (SSL版)${NC}"
    echo -e "${GREEN}===========================================${NC}"
    echo
    
    # 检查 root 权限
    check_root
    
    # 获取服务器IP
    get_server_ip
    
    # 确认安装
    echo -e "${YELLOW}即将在服务器 $SERVER_IP 上安装和配置 Squid 代理服务器${NC}"
    echo -e "${YELLOW}功能: HTTP/HTTPS代理 + SSL证书 + 账号密码认证${NC}"
    read -p "是否继续？(y/N): " CONFIRM
    if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
        log_info "安装已取消"
        exit 0
    fi
    
    # 执行安装步骤
    install_squid
    backup_config
    setup_auth
    setup_ssl
    create_config
    start_service
    show_info
    
    log_info "Squid 代理服务器安装和配置完成！"
}

# 运行主函数
main "$@"